#include "StdAfx.h"
#include "VItem.h"

// VProperty //////////////////////////////////////////////////////////////////

//
VProperty::VProperty(QObject *object) 
	:m_object(object) 
{
	if (qobject_cast<VItem*>(object))
		m_delta = 1;
	else
		m_delta = 0;
}

//
int VProperty::count() const 
{ 
	return m_object->metaObject()->propertyCount() - m_delta;
}

//
bool VProperty::setValue(int propIndex,const QVariant &value)
{
	if (propIndex < 0 || propIndex >= count())
		return false;

	propIndex += m_delta;
	
	QMetaProperty metaProperty = m_object->metaObject()->property(propIndex);
	m_object->setProperty(metaProperty.name(),value);

	return true;
}

//
bool VProperty::setValue(const QString &name,const QVariant &value)
{
	m_object->setProperty(name.toAscii().constData(),value);
	return true;
}

//
QString VProperty::name(int propIndex) const 
{ 
	propIndex += m_delta;
	return m_object->metaObject()->property(propIndex).name();
}

//
QVariant VProperty::value(int propIndex) const
{
	if (propIndex < 0 || propIndex >= count())
		return QVariant();

	propIndex += m_delta;

	QMetaProperty metaProperty = m_object->metaObject()->property(propIndex);
	return m_object->property(metaProperty.name());
}

//
QVariant VProperty::value(const QString &name) const
{
	return m_object->property(name.toAscii().constData());
}

//
QMetaProperty VProperty::metaProperty(int propIndex) const
{
	if (propIndex < 0 || propIndex >= count())
		Q_ASSERT(NULL);

	propIndex += m_delta;

	return m_object->metaObject()->property(propIndex);
}

//
int VProperty::propIndex(const QString &name) const
{
	return m_object->metaObject()->indexOfProperty(name.toAscii().constData()) - m_delta;
}

// VPropertyEnum ////////////////////////////////////////////////////

QMap<QString,QStringList> VPropertyEnum::m_map;

//
VPropertyEnum::VPropertyEnum(const QMetaProperty &prop)
	:m_prop(prop)
{														
	QString name = prop.name();
	if (name == VItem::propItemType())
		if (!m_map.contains(name))
			m_map[name] = VItem::EItemType_DisplayList();
}

//
QStringList VPropertyEnum::displayList() const
{
	QStringList list;
	if (!m_prop.isEnumType())
		return list;

	QString name = m_prop.name();
	if (m_map.contains(name))
		return m_map[name];

	QMetaEnum e = m_prop.enumerator();
	for (int i = 0; i < e.keyCount(); ++i)
		list << e.valueToKey(i);

	return list;
}

//
QString VPropertyEnum::display(const QVariant &value) const 
{ 
	QMetaEnum e = m_prop.enumerator();
	int v = value.toInt();

	if (v < 0 || v >= e.keyCount())
		v = 0;

	QString name = m_prop.name();
	if (m_map.contains(name))
		return m_map[name][v];

	return e.key(v);
}

// VItemStyle /////////////////////////////////////////////////////////////////

//
VItemStyle::VStyle VItemStyle::style(QObject *object,int propIndex)
{
	struct VData
	{
		VStyle item;
		VStyle itemType;
		VStyle folderName;
		VStyle tableName;

		VData()
		{
			item.font.setPointSize(10);
			item.color.setRgb(0,0,0, 255);

			itemType.font.setPointSize(10);
			itemType.font.setItalic(true);
			itemType.color.setRgb(0,0,240, 255);

			folderName.font.setPointSize(11);
			folderName.font.setBold(true);
			folderName.color.setRgb(0,0,0, 255);

			tableName.font.setPointSize(11);
			tableName.font.setBold(true);
			tableName.color.setRgb(0,0,0, 255);
		}
	};
	static VData data;

	VProperty prop(object);
	
	if (qobject_cast<VItem*>(object))
		if (prop.name(propIndex) == VItem::propItemType())
			return data.itemType;

	if (qobject_cast<VItemFolder*>(object))
		if (prop.name(propIndex) == VItem::propName())
			return data.folderName;
	
	if (qobject_cast<VItemTable*>(object))
		if (prop.name(propIndex) == VItem::propName())
			return data.tableName;

	return data.item;
}

// VItem //////////////////////////////////////////////////////////////////////

//
VItem::VItem() 
	:m_name("")
	,m_unicode("")
	,m_idName(0)
	,m_idNav(0)
	,m_idNavParent(0)
{
}

//
VItem *VItem::itemFactory(EItemType itemType)
{
	switch (itemType)
	{
		case EItemType_item:				return new VItem;
		case EItemType_folder:			return new VItemFolder;
		case EItemType_table:				return new VItemTable;
		//case EItemType_primaryKey:	return new VItemFieldPrimaryKey;
		case EItemType_mReference:	return new VItemMReference;
		case EItemType_string:			return new VItemString;
		case EItemType_integer:			return new VItemInteger;
	}
	Q_ASSERT(NULL);
	return NULL;
}

//
void VItem::copyFromItem(const VItem &item) 
{ 
	m_name = item.m_name; 
	m_unicode = item.m_unicode;
	m_idName = item.m_idName;
	m_idNav = item.m_idNav;
	m_idNavParent = item.m_idNavParent;
}

// VItemFolder ////////////////////////////////////////////////////////////////

//
void VItemFolder::copyFrom(const VItem &item) 
{ 
	VItemFolder *p = qobject_cast<VItemFolder*>(&const_cast<VItem&>(item));
	Q_ASSERT(p);
	VItem::copyFrom(item);
}

// VItemTable /////////////////////////////////////////////////////////////////

//
void VItemTable::copyFrom(const VItem &item) 
{ 
	VItemTable *p = qobject_cast<VItemTable*>(&const_cast<VItem&>(item));
	Q_ASSERT(p);
	VItem::copyFrom(item);
}

/*************
// VItemFieldPrimaryKey ///////////////////////////////////////////////////////

//
void VItemFieldPrimaryKey::copyFrom(const VItem &item) 
{ 
	VItemFieldPrimaryKey *p = qobject_cast<VItemFieldPrimaryKey*>(&const_cast<VItem&>(item));
	Q_ASSERT(p);
	VItem::copyFrom(item);
	m_value = p->m_value;
}
*****************/

// VDataMReference ////////////////////////////////////////////////////////////

//
void VDataMReference::setValue(const QVariant &value)
{ 
	Q_ASSERT(!qVariantCanConvert<VIntegerList>(value));
	m_value = qVariantValue<VIntegerList>(value);
	setIsNull(value.isNull());
}

//
void VDataMReference::copyFrom(const VDataField &from)
{
	VDataMReference *p = qobject_cast<VDataMReference*>(&const_cast<VDataField&>(from));
	Q_ASSERT(p);
	VDataField::copyFrom(from);
	m_value = p->m_value;
}

// VItemMReference ////////////////////////////////////////////////////////////

//
void VItemMReference::copyFrom(const VItem &item)
{ 
	VItemMReference *p = qobject_cast<VItemMReference*>(&const_cast<VItem&>(item));
	Q_ASSERT(p);
	VItem::copyFrom(item);
	m_idNavMaster = p->m_idNavMaster;
	m_value = p->m_value;
}

//
void VItemMReference::setVariantValue(const QVariant &value)
{ 
	Q_ASSERT(!qVariantCanConvert<VIntegerList>(value));
	m_value = qVariantValue<VIntegerList>(value);
}

// VDataString ////////////////////////////////////////////////////////////////

//
void VDataString::copyFrom(const VDataField &from)
{
	VDataString *p = qobject_cast<VDataString*>(&const_cast<VDataField&>(from));
	Q_ASSERT(p);
	VDataField::copyFrom(from);
	m_value = p->m_value;
}

// VItemString ////////////////////////////////////////////////////////////////

//
void VItemString::copyFrom(const VItem &item)
{ 
	VItemString *p = qobject_cast<VItemString*>(&const_cast<VItem&>(item));
	Q_ASSERT(p);
	VItem::copyFrom(item);
	m_length = p->m_length;
	m_value = p->m_value;
}

// VDataInteger ///////////////////////////////////////////////////////////////

//
void VDataInteger::copyFrom(const VDataField &from)
{
	VDataInteger *p = qobject_cast<VDataInteger*>(&const_cast<VDataField&>(from));
	Q_ASSERT(p);
	VDataField::copyFrom(from);
	m_value = p->m_value;
}

// VItemInteger ///////////////////////////////////////////////////////////////

//
void VItemInteger::copyFrom(const VItem &item)
{ 
	VItemInteger *p = qobject_cast<VItemInteger*>(&const_cast<VItem&>(item));
	Q_ASSERT(p);
	VItem::copyFrom(item);
	m_value = p->m_value;
}
